package com.zx.idc.backend.gui.shiro;


import com.zx.idc.common.spring.SpringConfigUtil;
import com.zx.idc.ds.tlog.service.ITLogActiveService;
import com.zx.idc.ds.tlog.service.ITLogSecurityService;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * shiro 初始化配置类
 *
 * @auth jinyuanf
 * @date 2019/4/28 11:45
 **/
@Configuration
public class ShiroConfig {

    @Autowired
    private ITLogSecurityService itLogSecurityService;

    @Autowired
    private TokenManagerUtil tokenManagerUtil;

    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator processor = new DefaultAdvisorAutoProxyCreator();
        processor.setProxyTargetClass(true);
        return processor;
    }

    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/system/login");
        shiroFilterFactoryBean.setSuccessUrl("/");
        shiroFilterFactoryBean.setUnauthorizedUrl("/common/forward?pagePath=error/401");
        Map<String, Filter> filters = new LinkedHashMap<>();
        filters.put("authc", new SysFormAuthenticationFilter());
        filters.put("perms", new PermissionsAuthorizationFilter(itLogSecurityService,tokenManagerUtil));
        shiroFilterFactoryBean.setFilters(filters);
        Map<String, String> chainDefinitionMap = new LinkedHashMap<>();
        chainDefinitionMap.put("/api/**", "authc,perms");
        chainDefinitionMap.put("/static/**", "anon");
        chainDefinitionMap.put("/services/**", "anon");
        chainDefinitionMap.put("/system/**", "anon");
        chainDefinitionMap.put("/error/**", "anon");
        chainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(chainDefinitionMap);
        return shiroFilterFactoryBean;
    }


    @Bean
    @DependsOn("initialConfig")
    public DefaultWebSessionManager sessionManager(ITLogActiveService itLogActiveService, RedisCacheManager redisCacheManager, ShiroSessionListener shiroSessionListener) {
        ShiroSessionManager sessionManager = new ShiroSessionManager();
        //设置session监听器
        List<SessionListener> sessionListeners = new ArrayList<>();
        sessionListeners.add(shiroSessionListener);
        sessionManager.setSessionListeners(sessionListeners);

        sessionManager.setSessionDAO(sessionDao(itLogActiveService, redisCacheManager));
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        //设置session过期时间
        sessionManager.setGlobalSessionTimeout(SpringConfigUtil.getInteger("cache.redis.timeout.session") * 1000);
        sessionManager.setDeleteInvalidSessions(true);
        sessionManager.setCacheManager(redisCacheManager);
        sessionManager.setSessionValidationSchedulerEnabled(false);
        Cookie sessionIdCookie = sessionManager.getSessionIdCookie();
        sessionIdCookie.setPath("/");
        sessionIdCookie.setName("csid");
        sessionManager.setSessionIdCookieEnabled(true);
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }

    @Bean
    @DependsOn("initialConfig")
    public DefaultWebSecurityManager securityManager(ITLogActiveService itLogActiveService, RedisCacheManager redisCacheManager, SysAuthorizingRealm sysAuthorizingRealm, ShiroSessionListener shiroSessionListener) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(sysAuthorizingRealm);
        securityManager.setCacheManager(redisCacheManager);
        // 设置通过shiro管理应用session
        securityManager.setSessionManager(sessionManager(itLogActiveService, redisCacheManager, shiroSessionListener));
        return securityManager;
    }

    @Bean
    @DependsOn("initialConfig")
    public RedisSessionDao sessionDao(ITLogActiveService itLogActiveService, RedisCacheManager redisCacheManager) {
        RedisSessionDao sessionDao = new RedisSessionDao();
        sessionDao.setTlogActiveService(itLogActiveService);
        sessionDao.setCacheManager(redisCacheManager);
        return sessionDao;
    }

    @Bean
    public FilterRegistrationBean delegatingFilterProxy() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        DelegatingFilterProxy proxy = new DelegatingFilterProxy();
        proxy.setTargetFilterLifecycle(true);
        proxy.setTargetBeanName("shiroFilter");
        filterRegistrationBean.setFilter(proxy);
        return filterRegistrationBean;
    }

}
